#include "glwidget.h"

//======================================================================================================================
//
//When press the delete button in edit mesh widget, call this function to delete select points or faces
//
//======================================================================================================================

void GLWidget::deleteSelect()
{
    if (selectMode==CELL_EDITMESHPOINT) {
        if (selectObject==0) {
            if(glandular->isSurfaceConstructed())
                glandular->deleteSelectPoint();
        } else if (selectObject>1) {
            objects[selectObject-2]->deleteSelectPoint();
        }
    } else if (selectMode==CELL_EDITMESHFACE) {
        if (selectObject==0) {
            if(glandular->isSurfaceConstructed())
                glandular->deleteSelectFace();
        } else if (selectObject>1) {
            objects[selectObject-2]->deleteSelectFace();
        }
    }
    updateGL();
}

//======================================================================================================================
//
//Under the edit mesh base on points selectmode, when click the left mouse button, call this function to return the select point.
//x:mouse click position x
//y:mouse click position y
//
//======================================================================================================================
void GLWidget::pickEditPoint(int x, int y)
{
    GLuint selectBuf[BUFSIZE];
    GLint hits;
    GLint viewport[4];
    glGetIntegerv(GL_VIEWPORT, viewport);
    glSelectBuffer(BUFSIZE, selectBuf);
    (void) glRenderMode(GL_SELECT);	/* Enter select mode */
    glInitNames();
    glPushName(0);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    //define a picking region
    gluPickMatrix((GLdouble) x,
                  (GLdouble) (viewport[3] - y),
                  10.0, 10.0,
                  viewport
                  );

    if (viewMode == CELL_PERSPECTIVE) {
        gluPerspective(45,(double)windowWidth/(double)windowHeight,0.01,1000);
    } else if (viewMode == CELL_TOP) {
        glOrtho(-topR*sin(pi/8), topR*sin(pi/8),
                -topR*sin(pi/8)*(double)windowHeight/(double)windowWidth,
                topR*sin(pi/8)*(double)windowHeight/(double)windowWidth,-INT_MAX,INT_MAX);
    } else if (viewMode == CELL_FRONT) {
        glOrtho(-frontR*sin(pi/8), frontR*sin(pi/8),
                -frontR*sin(pi/8)*(double)windowHeight/(double)windowWidth,
                frontR*sin(pi/8)*(double)windowHeight/(double)windowWidth,-INT_MAX,INT_MAX);
    } else if (viewMode == CELL_RIGHT) {
        glOrtho(-rightR*sin(pi/8), rightR*sin(pi/8),
                -rightR*sin(pi/8)*(double)windowHeight/(double)windowWidth,
                rightR*sin(pi/8)*(double)windowHeight/(double)windowWidth,-INT_MAX,INT_MAX);
    }

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    if (viewMode == CELL_PERSPECTIVE) {
        glTranslatef(offsetX,-offsetY,0);
        gluLookAt(R*cos(Phi)*cos(Theta), R*sin(Theta), R*sin(Phi)*cos(Theta),
                  0.0,0.0,0.0, 0.0,1.0,0.0);
    } else if (viewMode == CELL_TOP) {
        glTranslatef(topOffsetX,-topOffsetY,0);
        gluLookAt(topR*cos(0.0)*cos(pi/2), topR*sin(pi/2), topR*sin(0.0)*cos(pi/2),
                  0.0,0.0,0.0, 0.0,1.0,0.0);
    } else if (viewMode == CELL_FRONT) {
        glTranslatef(frontOffsetX,-frontOffsetY,0);
        gluLookAt(frontR*cos(0.0)*cos(0.0), frontR*sin(0.0), frontR*sin(0.0)*cos(0.0),
                  0.0,0.0,0.0, 0.0,1.0,0.0);
    } else if (viewMode == CELL_RIGHT) {
        glTranslatef(rightOffsetX,-rightOffsetY,0);
        gluLookAt(rightR*cos(pi/2)*cos(0.0), rightR*sin(0.0), rightR*sin(pi/2)*cos(0.0),
                  0.0,0.0,0.0, 0.0,1.0,0.0);
    }

    //highlight the point (calling drawEditPoint changes the color of the point for the viewer)
    if (selectObject==0) {
        if(glandular->isSurfaceConstructed())
            glandular->drawEditPoint();
    } else if (selectObject>1) {
        objects[selectObject-2]->drawEditPoint();
    }

    glFlush();
    hits = glRenderMode(GL_RENDER);
    processHits(hits, selectBuf, 4);
    int recPoint = -1;
    if (selectObject==0) {
        for (int i=0;i<glandular->getVerticeNum();i++) {
            if (glandular->isPointSelected(i)) {
                recPoint = i;
                break;
            }
        }
        if (recPoint>=0 && glandular->isSurfaceConstructed()) {
            Vector3 selectedP = glandular->getVertice(recPoint);
            for (int i=0;i<glandular->getVerticeNum();i++) {
                Vector3 recP = glandular->getVertice(i);
                if (selectedP.x==recP.x&&selectedP.y==recP.y&&selectedP.z==recP.z) {
                    glandular->setPointSelect(i);
                }
            }
        }
    } else if (selectObject>1) {
        for (int i=0;i<objects[selectObject-2]->getVerticeNum();i++) {
            if (objects[selectObject-2]->isPointSelected(i)) {
                recPoint = i;
                break;
            }
        }
        if (recPoint>=0) {
            Vector3 selectedP = objects[selectObject-2]->getVertice(recPoint);
            for (int i=0;i<objects[selectObject-2]->getVerticeNum();i++) {
                Vector3 recP = objects[selectObject-2]->getVertice(i);
                if (selectedP.x==recP.x&&selectedP.y==recP.y&&selectedP.z==recP.z) {
                    objects[selectObject-2]->setPointSelect(i);
                }
            }
        }
    }

    resizeGL(windowWidth, windowHeight);
}

//======================================================================================================================
//
//Under the edit mesh base on faces selectmode, when click the left mouse button, call this function to return the select face.
//x:mouse click position x
//y:mouse click position y
//
//======================================================================================================================

void GLWidget::pickEditFace(int x, int y)
{
    GLuint selectBuf[BUFSIZE];
    GLint hits;
    GLint viewport[4];
    glGetIntegerv(GL_VIEWPORT, viewport);
    glSelectBuffer(BUFSIZE, selectBuf);
    (void) glRenderMode(GL_SELECT);	/* Enter select mode */
    glInitNames();
    glPushName(0);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    gluPickMatrix((GLdouble) x,
                  (GLdouble) (viewport[3] - y),
                  10.0, 10.0,
                  viewport
                  );
    if (viewMode == CELL_PERSPECTIVE) {
        gluPerspective(45,(double)windowWidth/(double)windowHeight,0.01,1000);
    } else if (viewMode == CELL_TOP) {
        glOrtho(-topR*sin(pi/8), topR*sin(pi/8),
                -topR*sin(pi/8)*(double)windowHeight/(double)windowWidth,
                topR*sin(pi/8)*(double)windowHeight/(double)windowWidth,-INT_MAX,INT_MAX);
    } else if (viewMode == CELL_FRONT) {
        glOrtho(-frontR*sin(pi/8), frontR*sin(pi/8),
                -frontR*sin(pi/8)*(double)windowHeight/(double)windowWidth,
                frontR*sin(pi/8)*(double)windowHeight/(double)windowWidth,-INT_MAX,INT_MAX);
    } else if (viewMode == CELL_RIGHT) {
        glOrtho(-rightR*sin(pi/8), rightR*sin(pi/8),
                -rightR*sin(pi/8)*(double)windowHeight/(double)windowWidth,
                rightR*sin(pi/8)*(double)windowHeight/(double)windowWidth,-INT_MAX,INT_MAX);
    }

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    if (viewMode == CELL_PERSPECTIVE) {
        glTranslatef(offsetX,-offsetY,0);
        gluLookAt(R*cos(Phi)*cos(Theta), R*sin(Theta), R*sin(Phi)*cos(Theta),
                  0.0,0.0,0.0, 0.0,1.0,0.0);
    } else if (viewMode == CELL_TOP) {
        glTranslatef(topOffsetX,-topOffsetY,0);
        gluLookAt(topR*cos(0.0)*cos(pi/2), topR*sin(pi/2), topR*sin(0.0)*cos(pi/2),
                  0.0,0.0,0.0, 0.0,1.0,0.0);
    } else if (viewMode == CELL_FRONT) {
        glTranslatef(frontOffsetX,-frontOffsetY,0);
        gluLookAt(frontR*cos(0.0)*cos(0.0), frontR*sin(0.0), frontR*sin(0.0)*cos(0.0),
                  0.0,0.0,0.0, 0.0,1.0,0.0);
    } else if (viewMode == CELL_RIGHT) {
        glTranslatef(rightOffsetX,-rightOffsetY,0);
        gluLookAt(rightR*cos(pi/2)*cos(0.0), rightR*sin(0.0), rightR*sin(pi/2)*cos(0.0),
                  0.0,0.0,0.0, 0.0,1.0,0.0);
    }
    if (selectObject==0) {
        if(glandular->isSurfaceConstructed())
            glandular->drawEditFaces();
    } else if (selectObject>1) {
        objects[selectObject-2]->drawEditFaces();
    }

    glFlush();
    hits = glRenderMode(GL_RENDER);
    processHits(hits, selectBuf, 5);

    resizeGL(windowWidth, windowHeight);
}

//======================================================================================================================
//
//Under the edit mesh base on points selectmode, when click the left mouse button and drag, call this function to return all the points
//in the drag area.
//ax:mouse click position x
//ay:mouse click position y
//bx:mouse drag position x
//ay:mouse drag position y
//
//======================================================================================================================

void GLWidget::pickPointsInArea(int ax, int ay, int bx, int by)
{
    ax = min(max(0, ax),windowWidth-1);
    ay = min(max(0, ay),windowHeight-1);
    bx = min(max(0, bx),windowWidth-1);
    by = min(max(0, by),windowHeight-1);
    if (ax>bx) {
        int t=ax;
        ax=bx;
        bx=t;
    }
    if (ay>by) {
        int t=ay;
        ay=by;
        by=t;
    }

//    Vector3 position = Vector3(R*cos(Phi)*cos(Theta), R*sin(Theta), R*sin(Phi)*cos(Theta));
//    Vector3 view = Vector3(0.0, 0.0, 0.0)-position;
//    view.Normalize();
//    Vector3 up = Vector3(0.0, 1.0, 0.0);
//    float fov = 45.0;
//    float cnear = 0.01;
//    float cfar = 1000.0;

//    Vector3 right = Cross(view,up);
//    right.Normalize();

//    float ratio = (float)windowWidth/(float)windowHeight;
//    Vector3 newup = Cross(right,view);
//    newup.Normalize();
//    float nearwindowHeight = cnear*(float)tan(float(fov*pi/180.0f)/2.0f);
//    float nearwindowWidth  = nearwindowHeight*ratio;
//    float farwindowHeight  = cfar*(GLdouble)tan(GLdouble(fov*pi/180.0f)/2.0f);
//    float farwindowWidth   = farwindowHeight*ratio;
//    Vector3 nearCenter = position+view*cnear;
//    Vector3 farCenter = position+view*cfar;

//    Vector3 camera[8];
//    Vector3 point[8];
//    camera[0] = nearCenter - newup*nearwindowHeight - right*nearwindowWidth;
//    camera[1] = nearCenter - newup*nearwindowHeight + right*nearwindowWidth;
//    camera[2] = nearCenter + newup*nearwindowHeight + right*nearwindowWidth;
//    camera[3] = nearCenter + newup*nearwindowHeight - right*nearwindowWidth;

//    camera[4] = farCenter - newup*farwindowHeight - right*farwindowWidth;
//    camera[5] = farCenter - newup*farwindowHeight + right*farwindowWidth;
//    camera[6] = farCenter + newup*farwindowHeight + right*farwindowWidth;
//    camera[7] = farCenter + newup*farwindowHeight - right*farwindowWidth;

//    float x = (float)ax/(float)(windowWidth-1);
//    float y = 1.0-(float)by/(float)(windowHeight-1);
//    point[0]=(1.0-y)*(1.0-x)*camera[3]+(1.0-y)*x*camera[2]+y*x*camera[1]+y*(1.0-x)*camera[0];
//    x = (float)bx/(float)(windowWidth-1);
//    y = 1.0-(float)by/(float)(windowHeight-1);
//    point[1]=(1.0-y)*(1.0-x)*camera[3]+(1.0-y)*x*camera[2]+y*x*camera[1]+y*(1.0-x)*camera[0];
//    x = (float)bx/(float)(windowWidth-1);
//    y = 1.0-(float)ay/(float)(windowHeight-1);
//    point[2]=(1.0-y)*(1.0-x)*camera[3]+(1.0-y)*x*camera[2]+y*x*camera[1]+y*(1.0-x)*camera[0];
//    x = (float)ax/(float)(windowWidth-1);
//    y = 1.0-(float)ay/(float)(windowHeight-1);
//    point[3]=(1.0-y)*(1.0-x)*camera[3]+(1.0-y)*x*camera[2]+y*x*camera[1]+y*(1.0-x)*camera[0];

//    x = (float)ax/(float)(windowWidth-1);
//    y = 1.0-(float)by/(float)(windowHeight-1);
//    point[4]=(1.0-y)*(1.0-x)*camera[7]+(1.0-y)*x*camera[6]+y*x*camera[5]+y*(1.0-x)*camera[4];
//    x = (float)bx/(float)(windowWidth-1);
//    y = 1.0-(float)by/(float)(windowHeight-1);
//    point[5]=(1.0-y)*(1.0-x)*camera[7]+(1.0-y)*x*camera[6]+y*x*camera[5]+y*(1.0-x)*camera[4];
//    x = (float)bx/(float)(windowWidth-1);
//    y = 1.0-(float)ay/(float)(windowHeight-1);
//    point[6]=(1.0-y)*(1.0-x)*camera[7]+(1.0-y)*x*camera[6]+y*x*camera[5]+y*(1.0-x)*camera[4];
//    x = (float)ax/(float)(windowWidth-1);
//    y = 1.0-(float)ay/(float)(windowHeight-1);
//    point[7]=(1.0-y)*(1.0-x)*camera[7]+(1.0-y)*x*camera[6]+y*x*camera[5]+y*(1.0-x)*camera[4];

    GLint    viewport[4];
    GLdouble modelview[16];
    GLdouble projection[16];
    GLfloat  winX, winY;
    GLdouble posX, posY, posZ;
    Vector3 point[8];

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45,(double)windowWidth/(double)windowHeight,0.01,1000);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(R*cos(Phi)*cos(Theta), R*sin(Theta), R*sin(Phi)*cos(Theta),
              0.0,0.0,0.0, 0.0,1.0,0.0);
    glGetIntegerv(GL_VIEWPORT, viewport);
    glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
    glGetDoublev(GL_PROJECTION_MATRIX, projection);

    winX = (float)ax;
    winY = viewport[3] - (float)ay;
    gluUnProject(winX, winY, 0.0, modelview, projection, viewport, &posX, &posY, &posZ);
    point[3] = Vector3(posX, posY, posZ);
    winX = (float)bx;
    winY = viewport[3] - (float)ay;
    gluUnProject(winX, winY, 0.0, modelview, projection, viewport, &posX, &posY, &posZ);
    point[2] = Vector3(posX, posY, posZ);
    winX = (float)bx;
    winY = viewport[3] - (float)by;
    gluUnProject(winX, winY, 0.0, modelview, projection, viewport, &posX, &posY, &posZ);
    point[1] = Vector3(posX, posY, posZ);
    winX = (float)ax;
    winY = viewport[3] - (float)by;
    gluUnProject(winX, winY, 0.0, modelview, projection, viewport, &posX, &posY, &posZ);
    point[0] = Vector3(posX, posY, posZ);

    winX = (float)ax;
    winY = viewport[3] - (float)ay;
    gluUnProject(winX, winY, 1.0, modelview, projection, viewport, &posX, &posY, &posZ);
    point[7] = Vector3(posX, posY, posZ);
    winX = (float)bx;
    winY = viewport[3] - (float)ay;
    gluUnProject(winX, winY, 1.0, modelview, projection, viewport, &posX, &posY, &posZ);
    point[6] = Vector3(posX, posY, posZ);
    winX = (float)bx;
    winY = viewport[3] - (float)by;
    gluUnProject(winX, winY, 1.0, modelview, projection, viewport, &posX, &posY, &posZ);
    point[5] = Vector3(posX, posY, posZ);
    winX = (float)ax;
    winY = viewport[3] - (float)by;
    gluUnProject(winX, winY, 1.0, modelview, projection, viewport, &posX, &posY, &posZ);
    point[4] = Vector3(posX, posY, posZ);

    Vector3 view = Vector3(0.0-R*cos(Phi)*cos(Theta), 0.0-R*sin(Theta), 0.0-R*sin(Phi)*cos(Theta));
    view.Normalize();
    Vector3 up = Vector3(0.0, 1.0, 0.0);
    if (selectObject==0) {
        glandular->setPointsSelectInArea(point, view, up);
    } else if (selectObject>1) {
        objects[selectObject-2]->setPointsSelectInArea(point, view, up);
    }
}

//======================================================================================================================
//
//Under the edit mesh base on faces selectmode, when click the left mouse button and drag, call this function to return all the faces
//in the drag area.
//ax:mouse click position x
//ay:mouse click position y
//bx:mouse drag position x
//ay:mouse drag position y
//
//======================================================================================================================

void GLWidget::pickFacesInArea(int ax, int ay, int bx, int by)
{
    ax = min(max(0, ax),windowWidth-1);
    ay = min(max(0, ay),windowHeight-1);
    bx = min(max(0, bx),windowWidth-1);
    by = min(max(0, by),windowHeight-1);
    if (ax>bx) {
        int t=ax;
        ax=bx;
        bx=t;
    }
    if (ay>by) {
        int t=ay;
        ay=by;
        by=t;
    }

    GLint    viewport[4];
    GLdouble modelview[16];
    GLdouble projection[16];
    GLfloat  winX, winY;
    GLdouble posX, posY, posZ;
    Vector3 point[8];

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45,(double)windowWidth/(double)windowHeight,0.01,1000);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(R*cos(Phi)*cos(Theta), R*sin(Theta), R*sin(Phi)*cos(Theta),
              0.0,0.0,0.0, 0.0,1.0,0.0);
    glGetIntegerv(GL_VIEWPORT, viewport);
    glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
    glGetDoublev(GL_PROJECTION_MATRIX, projection);

    winX = (float)ax;
    winY = viewport[3] - (float)ay;
    gluUnProject(winX, winY, 0.0, modelview, projection, viewport, &posX, &posY, &posZ);
    point[3] = Vector3(posX, posY, posZ);
    winX = (float)bx;
    winY = viewport[3] - (float)ay;
    gluUnProject(winX, winY, 0.0, modelview, projection, viewport, &posX, &posY, &posZ);
    point[2] = Vector3(posX, posY, posZ);
    winX = (float)bx;
    winY = viewport[3] - (float)by;
    gluUnProject(winX, winY, 0.0, modelview, projection, viewport, &posX, &posY, &posZ);
    point[1] = Vector3(posX, posY, posZ);
    winX = (float)ax;
    winY = viewport[3] - (float)by;
    gluUnProject(winX, winY, 0.0, modelview, projection, viewport, &posX, &posY, &posZ);
    point[0] = Vector3(posX, posY, posZ);

    winX = (float)ax;
    winY = viewport[3] - (float)ay;
    gluUnProject(winX, winY, 1.0, modelview, projection, viewport, &posX, &posY, &posZ);
    point[7] = Vector3(posX, posY, posZ);
    winX = (float)bx;
    winY = viewport[3] - (float)ay;
    gluUnProject(winX, winY, 1.0, modelview, projection, viewport, &posX, &posY, &posZ);
    point[6] = Vector3(posX, posY, posZ);
    winX = (float)bx;
    winY = viewport[3] - (float)by;
    gluUnProject(winX, winY, 1.0, modelview, projection, viewport, &posX, &posY, &posZ);
    point[5] = Vector3(posX, posY, posZ);
    winX = (float)ax;
    winY = viewport[3] - (float)by;
    gluUnProject(winX, winY, 1.0, modelview, projection, viewport, &posX, &posY, &posZ);
    point[4] = Vector3(posX, posY, posZ);

    Vector3 view = Vector3(0.0-R*cos(Phi)*cos(Theta), 0.0-R*sin(Theta), 0.0-R*sin(Phi)*cos(Theta));
    view.Normalize();
    Vector3 up = Vector3(0.0, 1.0, 0.0);
    if (selectObject==0) {
        if(glandular->isSurfaceConstructed())
            glandular->setFacesSelectInArea(point, view, up);
    } else if (selectObject>1) {
        objects[selectObject-2]->setFacesSelectInArea(point, view, up);
    }
}

//======================================================================================================================
//
//Under the tanslate mode, when click the left mouse button, call this function to return the select tanslation axis
//x:mouse click position x
//y:mouse click position y
//tx:tanslation axis initial translation value x
//ty:tanslation axis initial translation value y
//tz:tanslation axis initial translation value z
//rx:tanslation axis initial rotation value x
//ry:tanslation axis initial rotation value y
//rz:tanslation axis initial rotation value z
//
//======================================================================================================================

void GLWidget::pickEditMeshTranslateAxis(int x, int y, double tx, double ty, double tz, double rx, double ry, double rz)
{
    GLuint selectBuf[BUFSIZE];
    GLint hits;
    GLint viewport[4];
    glGetIntegerv(GL_VIEWPORT, viewport);
    glSelectBuffer(BUFSIZE, selectBuf);
    (void) glRenderMode(GL_SELECT);	/* Enter select mode */
    glInitNames();
    glPushName(0);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    gluPickMatrix((GLdouble) x,
                  (GLdouble) (viewport[3] - y),
                  10.0, 10.0,
                  viewport
                  );
    if (viewMode == CELL_PERSPECTIVE) {
        gluPerspective(45,(double)windowWidth/(double)windowHeight,0.01,1000);
    } else if (viewMode == CELL_TOP) {
        glOrtho(-topR*sin(pi/8), topR*sin(pi/8),
                -topR*sin(pi/8)*(double)windowHeight/(double)windowWidth,
                topR*sin(pi/8)*(double)windowHeight/(double)windowWidth,-INT_MAX,INT_MAX);
    } else if (viewMode == CELL_FRONT) {
        glOrtho(-frontR*sin(pi/8), frontR*sin(pi/8),
                -frontR*sin(pi/8)*(double)windowHeight/(double)windowWidth,
                frontR*sin(pi/8)*(double)windowHeight/(double)windowWidth,-INT_MAX,INT_MAX);
    } else if (viewMode == CELL_RIGHT) {
        glOrtho(-rightR*sin(pi/8), rightR*sin(pi/8),
                -rightR*sin(pi/8)*(double)windowHeight/(double)windowWidth,
                rightR*sin(pi/8)*(double)windowHeight/(double)windowWidth,-INT_MAX,INT_MAX);
    }

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    if (viewMode == CELL_PERSPECTIVE) {
        glTranslatef(offsetX/R*2,-offsetY/R*2,0);
        gluLookAt(R*cos(Phi)*cos(Theta), R*sin(Theta), R*sin(Phi)*cos(Theta),
                  0.0,0.0,0.0, 0.0,1.0,0.0);
    } else if (viewMode == CELL_TOP) {
        glTranslatef(topOffsetX,-topOffsetY,0);
        gluLookAt(topR*cos(0.0)*cos(pi/2), topR*sin(pi/2), topR*sin(0.0)*cos(pi/2),
                  0.0,0.0,0.0, 0.0,1.0,0.0);
    } else if (viewMode == CELL_FRONT) {
        glTranslatef(frontOffsetX,-frontOffsetY,0);
        gluLookAt(frontR*cos(0.0)*cos(0.0), frontR*sin(0.0), frontR*sin(0.0)*cos(0.0),
                  0.0,0.0,0.0, 0.0,1.0,0.0);
    } else if (viewMode == CELL_RIGHT) {
        glTranslatef(rightOffsetX,-rightOffsetY,0);
        gluLookAt(rightR*cos(pi/2)*cos(0.0), rightR*sin(0.0), rightR*sin(pi/2)*cos(0.0),
                  0.0,0.0,0.0, 0.0,1.0,0.0);
    }
    drawEditMeshTranslateAxis(tx, ty, tz, rx, ry, rz);

    glFlush();
    hits = glRenderMode(GL_RENDER);
    processHits(hits, selectBuf, 1);

    resizeGL(windowWidth, windowHeight);
}

//======================================================================================================================
//
//Under the tanslate mode, call this function to draw tanslate axis at p(x, y, z)
//tx:tanslation axis initial translation value x
//ty:tanslation axis initial translation value y
//tz:tanslation axis initial translation value z
//rx:tanslation axis initial rotation value x
//ry:tanslation axis initial rotation value y
//rz:tanslation axis initial rotation value z
//
//======================================================================================================================

void GLWidget::drawEditMeshTranslateAxis(double x, double y, double z, double rx, double ry, double rz)
{
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
    glTranslatef(offsetX/R*2,-offsetY/R*2,0);
    if (viewMode == CELL_PERSPECTIVE) {
        gluLookAt(2*cos(Phi)*cos(Theta), 2*sin(Theta), 2*sin(Phi)*cos(Theta),
                  0.0,0.0,0.0, 0.0,1.0,0.0);
    } else if (viewMode == CELL_TOP) {
        gluLookAt(2*cos(0.0)*cos(pi/2), 2*sin(pi/2), 2*sin(0.0)*cos(pi/2),
                  0.0,0.0,0.0, 0.0,1.0,0.0);
    } else if (viewMode == CELL_FRONT) {
        gluLookAt(2*cos(0.0)*cos(0.0), 2*sin(0.0), 2*sin(0.0)*cos(0.0),
                  0.0,0.0,0.0, 0.0,1.0,0.0);
    } else if (viewMode == CELL_RIGHT) {
        gluLookAt(2*cos(pi/2)*cos(0.0), 2*sin(0.0), 2*sin(pi/2)*cos(0.0),
                  0.0,0.0,0.0, 0.0,1.0,0.0);
    }
    GLfloat axisLength = 0.2;
    // draw x axis in red, y axis in green, z axis in blue
    glPushMatrix();

    glTranslated(x/R*2.0, y/R*2.0, z/R*2.0);
    glRotated(rz, 0.0, 0.0, 1.0);
    glRotated(ry, 0.0, 1.0, 0.0);
    glRotated(rx, 1.0, 0.0, 0.0);

    x=0.0;
    y=0.0;
    z=0.0;

    glPushMatrix();
    glEnable(GL_LINE_SMOOTH);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
    glLineWidth(2.0);
    glLoadName(CELL_TRANSLATEAXISX);
    glBegin(GL_LINES);
    glColor3d(1.0, 0.2, 0.2);
    glVertex3d(x, y, z);
    glVertex3d(x+axisLength, y, z);
    glEnd();
    glEnable(GL_BLEND);
    glBlendFunc(GL_ZERO, GL_ONE);
    glLineWidth(5.0);
    glBegin(GL_LINES);
    glColor3d(1.0, 0.2, 0.2);
    glVertex3d(x, y, z);
    glVertex3d(x+axisLength*2, y, z);
    glEnd();
    glDisable(GL_BLEND);
    glRotated(90, 0, 1, 0);
    glTranslated(-z, y, x+axisLength);
    drawSolidCone(0.04, 0.01);
    glPopMatrix();

    glPushMatrix();
    glEnable(GL_LINE_SMOOTH);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
    glLineWidth(2.0);
    glLoadName(CELL_TRANSLATEAXISY);
    glBegin(GL_LINES);
    glColor3d(0.2, 1.0, 0.2);
    glVertex3d(x, y, z);
    glVertex3d(x, y+axisLength, z);
    glEnd();
    glEnable(GL_BLEND);
    glBlendFunc(GL_ZERO, GL_ONE);
    glLineWidth(5.0);
    glBegin(GL_LINES);
    glVertex3d(x, y, z);
    glVertex3d(x, y+axisLength*2, z);
    glEnd();
    glDisable(GL_BLEND);
    glRotated(-90, 1, 0, 0);
    glTranslated(x, -z, y+axisLength);
    drawSolidCone(0.04, 0.01);
    glPopMatrix();

    glPushMatrix();
    glEnable(GL_LINE_SMOOTH);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
    glLineWidth(2.0);
    glLoadName(CELL_TRANSLATEAXISZ);
    glBegin(GL_LINES);
    glColor3d(0.2, 0.2, 1.0);
    glVertex3d(x, y, z);
    glVertex3d(x, y, z+axisLength);
    glEnd();
    glEnable(GL_BLEND);
    glBlendFunc(GL_ZERO, GL_ONE);
    glLineWidth(5.0);
    glBegin(GL_LINES);
    glVertex3d(x, y, z);
    glVertex3d(x, y, z+axisLength*2);
    glEnd();
    glDisable(GL_BLEND);
    glRotated(-90, 0, 0, 1);
    glTranslated(-y, x, z+axisLength);
    drawSolidCone(0.04, 0.01);
    glPopMatrix();

    glPushMatrix();
    glEnable(GL_LINE_SMOOTH);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
    glLoadName(CELL_TRANSLATEAXISYZ);
    glLineWidth(1.0);
    glBegin(GL_LINES);
    glColor3d(0.2, 0.2, 1.0);
    glVertex3d(x, y, z+axisLength/4);
    glVertex3d(x, y+axisLength/4, z+axisLength/4);
    glColor3d(0.2, 1.0, 0.2);
    glVertex3d(x, y+axisLength/4, z);
    glVertex3d(x, y+axisLength/4, z+axisLength/4);
    glEnd();
    glEnable(GL_BLEND);
    glBlendFunc(GL_ZERO, GL_ONE);
    glBegin(GL_QUADS);
    glVertex3d(x, y, z);
    glVertex3d(x, y+axisLength/4, z);
    glVertex3d(x, y+axisLength/4, z+axisLength/4);
    glVertex3d(x, y, z+axisLength/4);
    glEnd();
    glDisable(GL_BLEND);
    glPopMatrix();

    glPushMatrix();
    glEnable(GL_LINE_SMOOTH);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
    glLoadName(CELL_TRANSLATEAXISXY);
    glLineWidth(1.0);
    glBegin(GL_LINES);
    glColor3d(1.0, 0.2, 0.2);
    glVertex3d(x+axisLength/4, y, z);
    glVertex3d(x+axisLength/4, y+axisLength/4, z);
    glColor3d(0.2, 1.0, 0.2);
    glVertex3d(x, y+axisLength/4, z);
    glVertex3d(x+axisLength/4, y+axisLength/4, z);
    glEnd();
    glEnable(GL_BLEND);
    glBlendFunc(GL_ZERO, GL_ONE);
    glBegin(GL_QUADS);
    glVertex3d(x, y, z);
    glVertex3d(x+axisLength/4, y, z);
    glVertex3d(x+axisLength/4, y+axisLength/4, z);
    glVertex3d(x, y+axisLength/4, z);
    glEnd();
    glDisable(GL_BLEND);
    glPopMatrix();

    glPushMatrix();
    glEnable(GL_LINE_SMOOTH);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
    glLoadName(CELL_TRANSLATEAXISZX);
    glLineWidth(1.0);
    glBegin(GL_LINES);
    glColor3d(1.0, 0.2, 0.2);
    glVertex3d(x+axisLength/4, y, z);
    glVertex3d(x+axisLength/4, y, z+axisLength/4);
    glColor3d(0.2, 0.2, 1.0);
    glVertex3d(x, y, z+axisLength/4);
    glVertex3d(x+axisLength/4, y, z+axisLength/4);
    glEnd();
    glEnable(GL_BLEND);
    glBlendFunc(GL_ZERO, GL_ONE);
    glBegin(GL_QUADS);
    glVertex3d(x, y, z);
    glVertex3d(x+axisLength/4, y, z);
    glVertex3d(x+axisLength/4, y, z+axisLength/4);
    glVertex3d(x, y, z+axisLength/4);
    glEnd();
    glDisable(GL_BLEND);
    glPopMatrix();
    glPopMatrix();

    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);
}

